#include "DIVA_Manager.h"
#include "ubrvm_line.h"
#include "vmLibrary.h"

#define COLOR_MODULATE_PARAM_INDEX 1
// @@@@
/// constructor
//Name           : hyt
//Update Date    : 08/10/26
//Update History :
//				(1) VL_createEntity 必須給 meshname,material可給可不給,若想自行命名vm的開頭,則可以
//                   再加第三個參數 string specialhead
//              (2) VL_regBoudingBox 則需要 vm的entity 
//              (3) 由programmer自行決定node內容
//              (4) 若要在vm任何一個位置顯示文字,首先呼叫VL_createVMText(你想顯示的文字,文字node的開頭name)
//                  再來是呼叫VL_createTextNode(vm文字位置)
//              (5) 設定vm node顏色則呼叫VL_setEntityColor(vm entity , Vector4(colorvalue))來設定
ubrvm_line::ubrvm_line(xParameterPack xpp):ReferenceVM(xpp){
	int default_port_number = vmLibrary::instance().get_vm_default_input_parameters().size();
	
	// reference vm is designed based on a proxy pattern
	// first, a reference vm has its own body
	// second, it must points to a vm (called pointed vm)
	// however, this pointed vm can be any vm and changed from time to time
	// so, a fixed vm passed to the constructor's parameters would not work.
	// so, a pragmatic way is to allowed user connect wop to a variable
	// in xNodeType_VM::createMappedObject(), we scan for hidden vm inport immediately
	// behind the wop. If there is a hidden vm inport, we use the wop to create a dummy vm
	// and feed this dummy as the parameter of the vm.  This dummy vm is designed based
	// on proxy pattern. The dummy vm is responsible for evaluating the wop value, search the 
	// represented VM and redirect the events and action to the vm.

	assert(xpp.no == default_port_number+3);
	_pointedVM = xpp.paras[default_port_number+1].val_vm ;  // @@@@ this _pointedVM is actually a dummyVM
	_proxyVM = (dummyVM *) _pointedVM ; // @@@@ cast it to dummyVM to use the method  isPointedNULL()
	_shapeVM = xpp.paras[default_port_number+2].val_vm ; // this is the VM which is used to 
	_myLine = false;
	_clicked = false;
	_line_node = NULL;

	VL_addVMAnimation();
	init_default_parameters(); // this line must be added at the end of each VM constructor
}

/// destructor
ubrvm_line::~ubrvm_line(){
}
void ubrvm_line::load_3Dresources(){

	Ogre::Vector3 pos=_shapeVM->getPosition(); 
	Ogre::SceneNode *parent = _shapeVM->getParentSceneNode() ;
	Ogre::SceneNode *s = _shapeVM->getSceneNode();
	parent->removeChild(s);
	_SceneNode->addChild(s);
	_shapeVM->setParentSceneNode(_SceneNode);
	_shapeVM->setPosition(pos);

}
void ubrvm_line::reg_event_entity() {

	// register the relation of the entity and vm in diva manager
	// When this entity is clicked, mouse/keyboard VM will be passed to this VM

	// In this VM, we do not have entity here
}
void ubrvm_line::set_default_values() {

	_vm_rx_val = 0 ;
	_vm_ry_val = 0 ;
	_vm_rz_val = 0 ;

	Ogre::Vector3 sz = this->getActualSize();
	_vm_init_sizex = sz.x ;
	_vm_init_sizey = sz.y ;
	_vm_init_sizez = sz.z ;

	_vm_sizex_val = sz.x ;
	_vm_sizey_val = sz.y ;
	_vm_sizez_val = sz.z ;

	_vm_sizexscale_val = 1.0 ;
	_vm_sizeyscale_val = 1.0 ;
	_vm_sizezscale_val = 1.0 ;

	_vm_r_val = 0.3;  // white color but with transparency 0.1
	_vm_g_val = 0.3;
	_vm_b_val = 0.3;
	_vm_transparency_val = 1.0 ;

	_vm_yaw_val = 0 ;
	_vm_pitch_val = 0 ;
	_vm_roll_val = 0 ;

}
void ubrvm_line::init_private_attrs_started() {

}
void ubrvm_line::init_color_and_transparency() {
	// we do not have entity in this VM
	// so we need to do nothing for color and transparency

}
void ubrvm_line::update_color_and_transparency() {
	init_color_and_transparency();
}
void ubrvm_line::VMValueUpdated() {
	_proxyVM->clearPointedVM();
	disableVMAnimation();
	if (_line_node != NULL) {
		DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->removeChild(_line_node);
		_line_node->detachAllObjects();		
	}
	
}
void ubrvm_line::VMAnimation(const Ogre::FrameEvent & evt){
	if (_visible == false){
		if(_line_node != NULL){
			DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->removeChild(_line_node);
			_line_node->detachAllObjects();
			//delete _myLine ;
			_line_node = NULL ;
			_myLine = NULL ;
		}
		return ;
	}
	if (!_proxyVM->hasNULLvalue()) { // @@@@@
		if(_proxyVM->getBodyVM()!= NULL &&
			_proxyVM->getBodyVM()->get_visible() == false){
			// this happens when _proxyVM has been re-pointed to an old existing VM and this VM is hidden
		   // due to scope change
			return;
		}
		Ogre::Vector3 start = getWorldPosition() ;
		Ogre::Vector3 end = _proxyVM->getWorldPosition();

		if (_line_node != NULL) {
			DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->removeChild(_line_node);
			_line_node->detachAllObjects();
			delete _myLine ;
		}
		_myLine = new Line3D();
		//_myLine->drawLine(Vector3(0,0,0), Vector3(200,200,200));

		_line_node = DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->createChildSceneNode();
		_line_node->attachObject(_myLine);
		_myLine->drawLine(start,end);
	}
}
void ubrvm_line::VMSetVisible(bool vis) {
	if (_visible != vis) {
		  _visible = vis ;
        _SceneNode->setVisible(vis);
		_shapeVM->VMSetVisible(vis);
	}	
}
void ubrvm_line::VMPicked(Ogre::Real x,Ogre::Real y,Ogre::Real z){

	enableVMAnimation();
	if (!_proxyVM->hasNULLvalue()) { // @@@@@
		if(_proxyVM->getBodyVM()!= NULL && !_proxyVM->getBodyVM()->get_visible()){
			_proxyVM->getBodyVM()->VMSetVisible(true);
		}
		_shapeVM->setColorandTransparency(Ogre::Vector4(1.0,1.0,1.0, 1.0f));
		Ogre::Vector3 start = getWorldPosition() ;
		Ogre::Vector3 end = _proxyVM->getWorldPosition();

		if (_line_node != NULL) {
			DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->removeChild(_line_node);
			_line_node->detachAllObjects();
			delete _myLine ;			
		}
		_myLine = new Line3D();
		_myLine->drawLine(start,end);

		//_myLine->drawLine(Vector3(0,0,0), Vector3(200,200,200));
		_line_node = DIVA_Manager::getInstance()->getSceneManager()->getRootSceneNode()->createChildSceneNode();
		_line_node->attachObject(_myLine);

	} else {
		// give the VM a black color 
		//Ogre::SubEntity* sub = _ent->getSubEntity(0);
		//sub->setCustomParameter(COLOR_MODULATE_PARAM_INDEX, Vector4(0.6f, 0.2f, 0.2f, 1.0f));
		_shapeVM->setColorandTransparency(Ogre::Vector4(0.6f, 0.2f, 0.2f, 1.0f));
	}
}

/** we must override this method because this vm has no entity 
Its entity is at _shapeVM 
*/
bool ubrvm_line::isSubComponent(DIVA_VM *vm) {
	// if _shapevm is an entity vm, the test is straightforward
	// if _shapevm is a composite vm, the test is passed to the composite vm
	// to recurively check if it is a subcomponent
	return _shapeVM->isSubComponent(vm);
}
void ubrvm_line::scaleBodyToAbsSize(Ogre::Vector3 v){
	setBodyScale(Ogre::Vector3(v.x/_vm_init_sizex,
		v.y/_vm_init_sizey,
		v.z/_vm_init_sizez));
}
void ubrvm_line::setBodyScale(Ogre::Vector3 scale) {
	_SceneNode->setScale(scale);
}
bool ubrvm_line::isBodyScaleWrtSceneNode() { return true ; }

Ogre::Vector3 ubrvm_line::getOriginalBodySize() {
	return Ogre::Vector3(_vm_init_sizex, _vm_init_sizey, _vm_init_sizez) ;
}

Ogre::Vector3 ubrvm_line::getActualSize() {
	Ogre::Vector3 size=_shapeVM ->getActualSize();
	return size ;
}
Ogre::Vector3 ubrvm_line::getBodyScale() {
	return _SceneNode->getScale();
}
